<?php

declare(strict_types=1);

namespace App\Common\Service;

use Hyperf\DbConnection\Db;

class BatchUpdateService
{
    /**
     * 批量更新数据.
     *
     * @param string $table 表名
     * @param array $data 更新数据数组
     * @param array $identifierFields 标识符字段名
     * @return mixed
     */
    public function batchUpdate(string $table, array $data, array $identifierFields): mixed
    {
        return Db::transaction(function () use ($table, $data, $identifierFields) {
            $caseStatements = [];
            $ids = [];

            // 构建 CASE WHEN 语句和条件
            foreach ($data as $item) {
                // 构建条件部分
                $conditionParts = [];
                foreach ($identifierFields as $field) {
                    if (!isset($item[$field])) {
                        throw new \InvalidArgumentException("Field $field is missing in the data array.");
                    }
                    $conditionParts[] = sprintf("%s = '%s'", $field, $item[$field]);
                }
                $conditionKey = implode(' AND ', $conditionParts);
                $ids[] = $conditionKey;

                foreach ($item as $field => $value) {
                    if (!in_array($field, $identifierFields)) {
                        $caseStatements[$field][] = sprintf(
                            "WHEN %s THEN '%s'",
                            $conditionKey,
                            $value
                        );
                    }
                }
            }

            // 生成更新 SQL 语句
            $updateParts = [];
            foreach ($caseStatements as $field => $cases) {
                $updateParts[] = sprintf(
                    "%s = CASE %s END",
                    $field,
                    implode(' ', $cases)
                );
            }

            $sql = sprintf(
                "UPDATE %s SET %s WHERE (%s)",
                $table,
                implode(', ', $updateParts),
                implode(' OR ', array_map(function($condition) {
                    return "($condition)";
                }, $ids))
            );
            return Db::statement($sql);
        });
    }

    public function batchUpdateWithCondition(
        string $table,
        array $data,
        array $uniqueBy,
        array $updateFields
    ): void {
        Db::table($table)->upsert($data, $uniqueBy, $updateFields);
    }

}